# -*- coding : utf_8 -*-
"""
=======================================
Time : 2025/4/8 18:20
Author : 田霄汉
Email : 522989570@qq.com
File : operation_date.py
Project : pandas_demo
=======================================
"""

import datetime as dt


class OperationDate:

    def get_current_days(self, str_date):
        """
        获取当前日期当年的总天数
        :param str_date: 当前日期
        :return: 当年的总天数
        """
        days_list = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
        try:
            current_date = dt.datetime.strptime(str_date, '%Y-%m-%d')
            year = current_date.year
            month = current_date.month
            day = current_date.day
            if month < 2:
                total = day
            else:
                total = 0
                for i in range(month - 1):
                    total += days_list[i]
                if year % 400 == 0 or year % 100 != 0 and year % 4 == 0:
                    total += 1
                total += day
            return total
        except Exception as E:
            print(f'错误信息：{E}')

    def get_total_days(self, str_date):
        """
        获取当前日期总的公元前天数
        :param str_date: 当前日期
        :return: 公元前总天数
        """
        try:
            current_date = dt.datetime.strptime(str_date, '%Y-%m-%d')
            year = current_date.year
            bissextile_year = []
            for i in range(1, year):
                if i % 400 == 0 or i % 100 != 0 and i % 4 == 0:
                    bissextile_year.append(i)
            bissextile_num = len(bissextile_year)
            year_total_days = bissextile_num * 366 + (year - bissextile_num - 1) * 365
            year_current_days = self.get_current_days(str_date)
            total = year_total_days + year_current_days
            return total
        except Exception as E:
            print(f"报错信息：{E}")

    def get_bissextiles(self, year):
        """
        获取当年年份以前(包含当年)有多少个闰年
        :param year: 当前年份
        :return: 闰年的数量
        """
        try:
            year = int(year)
            result = []
            for i in range(1, year + 1):
                if i % 400 == 0 or i % 100 != 0 and i % 4 == 0:
                    result.append(i)
            return len(result)
        except Exception as E:
            print(f'报错信息：{E}')

    def get_add_days(self, start_date, days):
        """
        计算start_date增加days后的日期
        :param start_date: 起始日期
        :param days: 增加天数
        :return: 增加后的日期
        """
        try:
            # 先将日期转换成公元前天数
            total_days = self.get_total_days(start_date)
            total_days += days
            # 每400年，因为第400年是闰年，所以有97个闰年+303个平年，周期是4*36524+1=146097天
            per_400 = (total_days // 146097) * 400
            other_400 = total_days % 146097
            # 每100年，因为第100年是平年，所以有24个闰年+76个平年，周期是25*1461-1=36524天
            per_100 = (other_400 // 36524) * 100
            other_100 = other_400 % 36524
            # 每4年，1个闰年+3个平年，周期是1461天
            per_4 = (other_100 // 1461) * 4
            other_4 = other_100 % 1461
            new_year = per_400 + per_100 + per_4

            # other_4大于1095就是在闰年中
            if other_4 > 1095:
                new_year += 4
                other_days = other_4 - 1095
                if other_days <= 31:
                    new_month = 1
                    new_day = other_days
                elif 31 < other_days <= 60:
                    new_month = 2
                    new_day = other_days - 31
                elif 60 < other_days <= 91:
                    new_month = 3
                    new_day = other_days - 60
                elif 91 < other_days <= 121:
                    new_month = 4
                    new_day = other_days - 91
                elif 121 < other_days <= 152:
                    new_month = 5
                    new_day = other_days - 121
                elif 152 < other_days <= 182:
                    new_month = 6
                    new_day = other_days - 152
                elif 182 < other_days <= 213:
                    new_month = 7
                    new_day = other_days - 182
                elif 213 < other_days <= 244:
                    new_month = 8
                    new_day = other_days - 213
                elif 244 < other_days <= 274:
                    new_month = 9
                    new_day = other_days - 244
                elif 274 < other_days <= 305:
                    new_month = 10
                    new_day = other_days - 274
                elif 305 < other_days <= 335:
                    new_month = 11
                    new_day = other_days - 305
                else:
                    new_month = 12
                    new_day = other_days - 335
            # other_4小于等于1095就在平年中，other_4=0就刚好在闰年周期，月和日直接赋值12-31
            else:
                if 730 < other_4:
                    new_year += 3
                    other_days = other_4 - 730
                elif 365 < other_4 <= 730:
                    new_year += 2
                    other_days = other_4 - 365
                elif 0 < other_4 <= 365:
                    new_year += 1
                    other_days = other_4
                # other_4等于0，其实就是刚好一个闰年周期，例如2000年，2012年，2016年，月就是12，日就是31
                else:
                    other_days = other_4

                # 如果刚好是一个闰年周期，月就是12，日就是31，年不用加
                if other_days == 0:
                    new_month = 12
                    new_day = 31
                elif 0 < other_days <= 31:
                    new_month = 1
                    new_day = other_days
                elif 31 < other_days <= 59:
                    new_month = 2
                    new_day = other_days - 31
                elif 59 < other_days <= 90:
                    new_month = 3
                    new_day = other_days - 59
                elif 90 < other_days <= 120:
                    new_month = 4
                    new_day = other_days - 90
                elif 120 < other_days <= 151:
                    new_month = 5
                    new_day = other_days - 120
                elif 151 < other_days <= 181:
                    new_month = 6
                    new_day = other_days - 151
                elif 181 < other_days <= 212:
                    new_month = 7
                    new_day = other_days - 181
                elif 212 < other_days <= 243:
                    new_month = 8
                    new_day = other_days - 212
                elif 243 < other_days <= 273:
                    new_month = 9
                    new_day = other_days - 243
                elif 273 < other_days <= 304:
                    new_month = 10
                    new_day = other_days - 273
                elif 304 < other_days <= 334:
                    new_month = 11
                    new_day = other_days - 304
                else:
                    new_month = 12
                    new_day = other_days - 334

            return f'{new_year}-{new_month}-{new_day}'

        except Exception as E:
            print(f'报错信息：{E}')

    def get_add_months(self, start_date, months):
        """
        计算start_date增加months后的日期
        :param start_date: 起始日期
        :param months: 增加月数
        :return: 增加后的日期
        """
        try:
            start_date = dt.datetime.strptime(start_date, '%Y-%m-%d')
            current_month = start_date.month
            current_year = start_date.year
            current_day = start_date.day
            new_month = current_month + months
            # new_month小于等于12，new_year不用做改动
            if new_month <= 12:
                new_month = new_month
                new_year = current_year
            # new_month大于12，new_year需要增加相应的年数
            else:
                add_years = new_month // 12
                new_month = new_month % 12
                # 如果new_month刚好等于0，那new_month其实就刚好在12月份
                if new_month == 0:
                    new_month = 12
                    # add_years也相对应的要减1年
                    add_years = add_years - 1
                new_year = current_year + add_years

            # 以下是一些特殊情况
            # 注意一下new_month为2月份的情况
            if new_month == 2:
                # 注意current_day是29，30，31的日期
                if current_day in [29, 30, 31]:
                    # 如果是闰年，就直接指定成2月29日
                    if new_year % 400 == 0 or new_year % 100 != 0 and new_year % 4 == 0:
                        return f'{new_year}-2-29'
                    # 如果是平年，就直接指定成2月28日
                    else:
                        return f'{new_year}-2-28'
            elif new_month in [4, 6, 9, 11]:
                if current_day == 31:
                    return f'{new_year}-{new_month}-30'

            return f'{new_year}-{new_month}-{current_day}'

        except Exception as E:
            print(f'错误信息：{E}')
